<template>
	<view class="editor-container">
		<view class="editor" :style="{height: editorHeight <= 0 ? 'auto': `${editorHeight}px`}">
			<!-- #ifdef H5 -->
			<web-editor id="editor" @ready="onEditorReady" @statuschange="onStatusChange"
				@textchange="(e) => $emit('textchange', e)" showImgSize showImgToolbar showImgResize
				:upload-handler="uploadHandlerForH5" @focus="onEditorFocus" @blur="onEditorBlur"></web-editor>
			<!-- #endif -->

			<!-- #ifndef H5 -->
			<editor id="editor" class="ql-container" placeholder="输入内容" @ready="onEditorReady"
				@statuschange="onStatusChange" showImgSize showImgToolbar showImgResize @focus="onEditorFocus"
				@blur="onEditorBlur"></editor>
			<!-- #endif -->
		</view>
		<view class="editor-toolbar pc">
			<view class="editor-toolbar-box">
				<tool-undo @change="({type, value}) => format(type, value)" :disabled="!showFooterToolBar"></tool-undo>
				<tool-redo @change="({type, value}) => format(type, value)" :disabled="!showFooterToolBar"></tool-redo>
				<tool-format-clear @change="({type, value}) => format(type, value)"
					:disabled="!showFooterToolBar"></tool-format-clear>
				<view class="editor-toolbar-divider"></view>
				<tool-header @change="({type, value}) => format(type, value)" :active="formats.header"
					:disabled="!showFooterToolBar"></tool-header>
				<tool-font-size @change="({type, value}) => format(type, value)" :active="formats.fontSize"
					:disabled="!showFooterToolBar"></tool-font-size>
				<tool-bold @change="({type, value}) => format(type, value)" :active="formats.bold"
					:disabled="!showFooterToolBar"></tool-bold>
				<tool-italic @change="({type, value}) => format(type, value)" :active="formats.italic"
					:disabled="!showFooterToolBar"></tool-italic>
				<tool-strike @change="({type, value}) => format(type, value)" :active="formats.strike"
					:disabled="!showFooterToolBar"></tool-strike>
				<tool-underline @change="({type, value}) => format(type, value)" :active="formats.underline"
					:disabled="!showFooterToolBar"></tool-underline>
				<tool-link @change="({type, value}) => format(type, value)" :active="formats.link"
					:disabled="!showFooterToolBar"></tool-link>
				<tool-align @change="({type, value}) => format(type, value)" :active="formats.align"
					:disabled="!showFooterToolBar"></tool-align>
				<tool-hr @change="({type, value}) => format(type, value)" :disabled="!showFooterToolBar"></tool-hr>
				<tool-list @change="({type, value}) => format(type, value)" :active="formats.list"
					:disabled="!showFooterToolBar"></tool-list>
				<tool-line-indent @change="({type, value}) => format(type, value)" :active="formats.textIndent"
					:disabled="!showFooterToolBar"></tool-line-indent>
				<tool-space-both @change="({type, value}) => format(type, value)"
					:active="formats.marginLeft && formats.marginRight"
					:disabled="!showFooterToolBar"></tool-space-both>
				<tool-line-height @change="({type, value}) => format(type, value)" :active="formats.lineHeight"
					:disabled="!showFooterToolBar"></tool-line-height>
				<tool-letter-space @change="({type, value}) => format(type, value)" :active="formats.letterSpacing"
					:disabled="!showFooterToolBar"></tool-letter-space>
				<view class="editor-toolbar-divider"></view>
				<tool-background @change="({type, value}) => format(type, value)" :active="formats.background"
					:disabled="!showFooterToolBar"></tool-background>
				<tool-color @change="({type, value}) => format(type, value)" :active="formats.color"
					:disabled="!showFooterToolBar"></tool-color>
				<view class="editor-toolbar-divider"></view>
				<tool-image @change="({type, value}) => format(type, value)"
					:disabled="!showFooterToolBar"></tool-image>
				<tool-video @change="({type, value}) => format(type, value)"
					:disabled="!showFooterToolBar"></tool-video>
				<tool-unlock-content @change="({type, value}) => format(type, value)"
					:disabled="!showFooterToolBar"></tool-unlock-content>
				<tool-ai @change="({type, value}) => format(type, value)" :active="showImChat"
					:disabled="!showFooterToolBar"></tool-ai>
			</view>
		</view>
		<view class="editor-toolbar m" :hidden="!showFooterToolBar"
			:style="{transform: `translateY(-${keyboardHeight}px)`}" @touchend.stop="">
			<view class="editor-toolbar-tools">
				<view class="tool" @click="showInsertBlockView">
					<uni-icons type="plus" size="60rpx" />
				</view>
				<view class="editor-toolbar-divider"></view>
				<view :class="{tool: true, active: showToolPopup === 'm-tool-header'}"
					@click="showToolPopupView('m-tool-header')" id="m-tool-header">
					<uni-icons custom-prefix="editor-icon" type="icon-text-group" size="54rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: showToolPopup === 'm-tool-text'}"
					@click="showToolPopupView('m-tool-text')" id="m-tool-text">
					<uni-icons custom-prefix="editor-icon" type="icon-attr-group" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: showToolPopup === 'm-tool-align'}"
					@click="showToolPopupView('m-tool-align')" id="m-tool-align">
					<uni-icons custom-prefix="editor-icon" type="icon-align-left" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.link}" @click="showLinkPopup(formats.link)">
					<uni-icons custom-prefix="editor-icon" type="icon-link" size="60rpx"></uni-icons>
				</view>
				<view class="tool" @click="() => $refs.insertImageDrawer.open()">
					<uni-icons custom-prefix="editor-icon" type="icon-image" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true}" @click="format('ai')">
					<uni-icons custom-prefix="editor-icon" type="icon-ai" size="60rpx" color="#b454ff"></uni-icons>
				</view>
				<view class="editor-toolbar-divider"></view>
				<view class="tool hide-keyboard" @click="hideKeyboard()">
					<uni-icons custom-prefix="editor-icon" type="icon-jianpan" size="70rpx"></uni-icons>
				</view>
			</view>
			<view class="editor-toolbar-popup" id="m-tool-header-popup"
				:class="{show: showToolPopup === 'm-tool-header'}"
				:style="{left: `${toolPopupRect.left}px`, right: `${toolPopupRect.right}px`}">
				<view :class="{tool: true, active: formats.header === 1}" @click="format('header', 1)">
					<uni-icons custom-prefix="editor-icon" type="icon-header1" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.header === 2}" @click="format('header', 2)">
					<uni-icons custom-prefix="editor-icon" type="icon-header2" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.header === 3}" @click="format('header', 3)">
					<uni-icons custom-prefix="editor-icon" type="icon-header3" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.header === 4}" @click="format('header', 4)">
					<uni-icons custom-prefix="editor-icon" type="icon-header4" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.header === 5}" @click="format('header', 5)">
					<uni-icons custom-prefix="editor-icon" type="icon-header5" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.header === 6}" @click="format('header', 6)">
					<uni-icons custom-prefix="editor-icon" type="icon-header6" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.list === 'ordered'}" @click="format('list', 'ordered')">
					<uni-icons custom-prefix="editor-icon" type="icon-ul" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.list === 'bullet'}" @click="format('list', 'bullet')">
					<uni-icons custom-prefix="editor-icon" type="icon-ol" size="60rpx"></uni-icons>
				</view>
			</view>
			<view class="editor-toolbar-popup" id="m-tool-text-popup" :class="{show: showToolPopup === 'm-tool-text'}"
				:style="{left: `${toolPopupRect.left}px`, right: `${toolPopupRect.right}px`}">
				<view :class="{tool: true, active: formats.bold}" @click="format('bold')">
					<uni-icons custom-prefix="editor-icon" type="icon-bold" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.italic}" @click="format('italic')">
					<uni-icons custom-prefix="editor-icon" type="icon-italic" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.underline}" @click="format('underline')">
					<uni-icons custom-prefix="editor-icon" type="icon-underline" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.strike}" @click="format('strike')">
					<uni-icons custom-prefix="editor-icon" type="icon-strike" size="60rpx"></uni-icons>
				</view>
			</view>
			<view class="editor-toolbar-popup" id="m-tool-align-popup" :class="{show: showToolPopup === 'm-tool-align'}"
				:style="{left: `${toolPopupRect.left}px`, right: `${toolPopupRect.right}px`}">
				<view :class="{tool: true, active: formats.indent}"
					@click="format('indent', formats.indent ? '-1' : '+1')">
					<uni-icons custom-prefix="editor-icon" type="icon-line-indent" size="48rpx"></uni-icons>
				</view>
				<view class="editor-toolbar-popup-divider"></view>
				<view :class="{tool: true, active: formats.align === 'left'}" @click="format('align', 'left')">
					<uni-icons custom-prefix="editor-icon" type="icon-align-left" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.align === 'center'}" @click="format('align', 'center')">
					<uni-icons custom-prefix="editor-icon" type="icon-align-center" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.align === 'right'}" @click="format('align', 'right')">
					<uni-icons custom-prefix="editor-icon" type="icon-align-right" size="60rpx"></uni-icons>
				</view>
				<view :class="{tool: true, active: formats.align === 'justify'}" @click="format('align', 'justify')">
					<uni-icons custom-prefix="editor-icon" type="icon-align-justify" size="60rpx"></uni-icons>
				</view>
			</view>
		</view>
		<uni-transition :mode-class="['slide-bottom', 'fade']" :show="showInsertBlockToolSetting" class="tool-setting">
			<view>
				<view class="tool-setting-header">
					<view class="close" @click="closeToolSetting">
						<uni-icons type="closeempty" size="40rpx" class="icon" />
					</view>
					<text>添加</text>
				</view>
				<view class="body insert-block">
					<view class="item" @click="() => $refs.insertImageDrawer.open()">
						<view class="icon">
							<uni-icons custom-prefix="editor-icon" type="icon-image" size="70rpx"></uni-icons>
						</view>
						<text class="text">图片</text>
					</view>
					<view class="item" @click="format('hr')">
						<view class="icon">
							<uni-icons custom-prefix="editor-icon" type="icon-hr" size="70rpx"></uni-icons>
						</view>
						<text class="text">分割线</text>
					</view>
					<view class="item" @click="format('unlockContent')">
						<view class="icon">
							<uni-icons custom-prefix="editor-icon" type="icon-unlock" size="70rpx"></uni-icons>
						</view>
						<text class="text">看广告解锁</text>
					</view>
				</view>
			</view>
		</uni-transition>
		<uni-transition :show="showToolSettingMask">
			<view class="tool-setting-mask"></view>
		</uni-transition>

		<uni-popup ref="popup" type="center">
			<view class="popup-body" @touchend.stop="">
				<!-- #ifndef H5 -->
				<view class="tip">
					<text>由于平台限制，插入超链接将转换为Markdown格式，不影响内容展示</text>
				</view>
				<!-- #endif -->
				<uni-forms label-width="90px">
					<uni-forms-item label="链接名称" name="link">
						<uni-easyinput v-model="currentLink.title" />
					</uni-forms-item>
					<uni-forms-item label="链接地址" name="link">
						<uni-easyinput v-model="currentLink.url" />
					</uni-forms-item>
				</uni-forms>
				<view class="popup-body-btn-group">
					<button class="btn" size="mini" @click="$refs.popup.close()">取消</button>
					<button class="btn" size="mini" type="primary" @click="linkChange">确定</button>
				</view>
			</view>
		</uni-popup>

		<view class="uni-im-chat-components" :hidden="!showImChat">
			<view class="close-bar">
				<view class="head">
					<text class="title">uni-ai-chat</text>
					<text class="desc">输入prompt提示词后AI根据你的输入生成文章</text>
				</view>
				<view class="close" @click="showImChat=false">
					<uni-icons type="closeempty" size="40rpx" class="icon"></uni-icons>
				</view>
			</view>
			<uni-im-chat ref="uniImChat"></uni-im-chat>
		</view>

		<uni-drawer class="insert-image-drawer" v-if="drawerWidth" ref="insertImageDrawer" mode="right"
			:width="drawerWidth">
			<uni-media-library mode="picker" :selected-count="1" :media-tabs="['image']"
				@onInsert="onInsertImage"></uni-media-library>
		</uni-drawer>
	</view>
</template>

<script>
	// 导入编辑器相关组件
	// 导入工具栏中的空格、行高、字间距、背景、图片、清除格式、解锁内容、AI等组件。同时导入WebEditor组件。
	import ToolColor from "./tools/color.vue";
	import ToolBold from "./tools/bold.vue";
	import ToolItalic from "./tools/italic.vue";
	import ToolStrike from "./tools/strike.vue";
	import ToolList from "./tools/list.vue";
	import ToolHr from "./tools/hr.vue";
	import ToolUndo from "./tools/undo.vue";
	import ToolRedo from "./tools/redo.vue";
	import ToolHeader from "./tools/header.vue";
	import ToolAlign from "./tools/align.vue";
	import ToolLink from "./tools/link.vue";
	import ToolUnderline from "./tools/underline.vue";
	import ToolLineIndent from "./tools/line-indent.vue";
	import ToolSpaceBoth from "./tools/space-both.vue";
	import ToolLineHeight from "./tools/line-height.vue";
	import ToolLetterSpace from "./tools/letter-space.vue";
	import ToolBackground from "./tools/background.vue";
	import ToolImage from "./tools/image.vue";
	import ToolFormatClear from "./tools/format-clear.vue";
	import ToolUnlockContent from "./tools/unlock-content.vue";
	import ToolAi from "./tools/ai.vue";
	import ToolVideo from "./tools/video.vue";
	import uniImChat from '../ai/chat.vue';
	import ToolFontSize from './tools/font-size.vue'

	// #ifdef H5
	import WebEditor from "./web/editor.vue";
	// #endif

	export default {
		name: "editor",
		emits: ['change', 'textchange'],
		components: {
			ToolBackground,
			ToolLetterSpace,
			ToolLineHeight,
			ToolLineIndent,
			ToolUnderline,
			ToolAlign,
			ToolUndo,
			ToolItalic,
			ToolBold,
			ToolStrike,
			ToolList,
			ToolHr,
			ToolRedo,
			ToolHeader,
			ToolLink,
			ToolSpaceBoth,
			ToolImage,
			ToolColor,
			ToolFormatClear,
			ToolUnlockContent,
			ToolAi,
			ToolVideo,
			uniImChat,
			ToolFontSize,
			// #ifdef H5
			WebEditor,
			// #endif
		},
		data() {
			return {
				formats: {}, // 编辑器格式状态
				keyboardHeight: 0, // 键盘高度
				showFooterToolBar: false, // 是否显示底部工具栏
				showToolSettingMask: false, // 是否显示工具栏设置遮罩层
				showInsertBlockToolSetting: false, // 是否显示插入块工具栏
				showToolPopup: '', // 当前工具栏弹出的工具名称，为空则表示没有弹出的工具
				toolPopupRect: {}, // 弹出工具栏的位置和大小
				showImChat: false, // 是否显示 AI 聊天窗口
				currentLink: { // 当前链接的信息
					title: '', // 链接标题
					url: '' // 链接URL
				},
				drawerWidth: 0, // 插入图片抽屉宽度
			}
		},
		computed: {
			// `editorHeight`计算属性，返回编辑器高度。当键盘弹出时，编辑器高度为键盘高度减去工具栏高度，否则为窗口高度减去工具栏高度
			editorHeight() {
				// toolbar 默认高度
				const toolbarHeight = 150
				let toolHeight = 0

				// 如果有弹出框，设置弹出框高度为50
				if (this.showToolPopup !== '') {
					toolHeight = 50
				}
				// 如果键盘高度大于0，返回窗口高度减去键盘高度减去工具栏高度减去工具栏弹出框高度，否则返回0。
				return this.keyboardHeight > 0 ? (this.systemInfo.windowHeight - this.keyboardHeight - toolbarHeight -
					toolHeight) : 0
			}
		},
		watch: {
			// 监听`showFooterToolBar`属性，当值为false时，清空弹出工具栏名称和弹出工具栏位置信息
			showFooterToolBar(newValue) {
				if (!newValue) {
					this.showToolPopup = ''
					this.toolPopupRect = {}
				}
			}
		},
		mounted() {
			// 调用`uni.getSystemInfoSync()`获取系统信息，保存到`systemInfo`属性中。
			this.systemInfo = uni.getSystemInfoSync()
			// 设置插入图片抽屉宽度为窗口宽度的80%
			this.drawerWidth = this.systemInfo.windowWidth * .8
		},
		methods: {
			// 编辑器加载完成时触发
			onEditorReady(editorCtx) {
				// 通过 #ifdef 条件编译根据不同的平台执行不同的操作

				// #ifdef H5
				// // 在 H5 平台上，将编辑器的 `editorCtx` 对象保存到组件的 `editorCtx` 属性中，并触发 `ready` 事件，将 `editorCtx` 对象作为参数传递给父组件。
				if (editorCtx) {
					this.editorCtx = editorCtx
					this.$emit('ready', editorCtx)
				}
				// // 在 H5 平台上，为了实现键盘弹出时自动调整编辑器高度，监听 `window.visualViewport` 对象的 `resize` 事件，并绑定 `resizeHandler` 方法。
				window.visualViewport.addEventListener('resize', resizeHandler.bind(this));

				function resizeHandler() {
					// 获取窗口高度和 `visualViewport` 高度
					const innerHeight = window.innerHeight
					const visualViewportHeight = window.visualViewport.height

					// 如果键盘高度大于0，调用 `this.onKeyboardHeightChange()` 方法，传入一个对象作为参数，对象包含 `height` 和 `duration` 两个属性，分别表示键盘高度和键盘弹出动画的持续时间，否则不做任何操作。
					this.onKeyboardHeightChange({
						height: parseInt(innerHeight - visualViewportHeight),
						duration: 0
					})
				}

				// #endif

				// #ifndef H5
				// 在非 H5 平台上，调用 `this.createSelectorQuery()` 方法获取编辑器的 `editorCtx` 对象，并将其保存到组件的 `editorCtx` 属性中。
				this.createSelectorQuery().select('#editor').context((res) => {
					this.editorCtx = res.context
					// 将 `editorCtx` 对象作为参数传递给父组件。
					this.$emit('ready', res.context)
				}).exec()
				// 监听键盘高度变化事件
				uni.onKeyboardHeightChange(this.onKeyboardHeightChange.bind(this))
				// #endif
			},
			// 监听键盘高度变化事件
			onKeyboardHeightChange(res) {
				// 如果键盘高度等于 `this.keyboardHeight`，则直接返回。
				if (res.height < 20 || res.height === this.keyboardHeight) return
				// 根据 `res.height` 的值设置 `duration` 变量的值，如果 `res.height` 大于 0，则将 `duration` 的值设置为 `res.duration * 1000`，否则将其设置为 0。
				const duration = res.height > 0 ? res.duration * 1000 : 0
				// 调用 `setTimeout` 函数，将 `uni.pageScrollTo` 方法的调用放入异步任务队列中，以确保在页面滚动到顶部后再更新编辑器的位置。
				setTimeout(() => {
					uni.pageScrollTo({
						scrollTop: 0,
						success: () => {
							// 在页面滚动到顶部后，调用 `this.updatePosition()` 方法，传入 `res.height` 作为参数，更新编辑器的位置。
							this.updatePosition(res.height)
							// 调用 `this.editorCtx.scrollIntoView()` 方法，将编辑器滚动到可视区域内。
							setTimeout(() => this.editorCtx.scrollIntoView(), 0)
						}
					})
				}, duration)
			},
			// 更新键盘高度
			updatePosition(keyboardHeight) {
				this.keyboardHeight = keyboardHeight
			},
			// 显示工具栏弹出层
			showToolPopupView(id) {
				uni.createSelectorQuery().in(this).select('#' + id).boundingClientRect(btnData => {
					uni.createSelectorQuery().in(this).select('#' + id + '-popup').boundingClientRect(
					popupData => {
						const center = popupData.width / 2

						// 根据位置信息计算出工具栏弹出层的位置，始终将弹出层显示在最中间，将位置信息保存到组件的 `toolPopupRect` 属性中
						if (btnData.left > center) {
							this.toolPopupRect.left = (btnData.left - center) + btnData.width / 2
						} else {
							this.toolPopupRect.left = 10
						}
						if (popupData.width > this.systemInfo.windowWidth) {
							this.toolPopupRect.right = 10
						}

						// 根据传递的id参数，设置组件的 `showToolPopup` 属性的值，如果 `showToolPopup` 属性的值等于传递的id参数，则将其设置为空字符串（隐藏工具栏弹出层），否则将其设置为传递的id参数（显示工具栏弹出层）。
						this.showToolPopup = this.showToolPopup !== id ? id : ''
						// 如果 `showToolPopup` 属性的值为空字符串，则将组件的 `toolPopupRect` 属性设置为空对象，清空工具栏弹出层位置信息。
						if (this.showToolPopup === '') {
							this.toolPopupRect = {}
						}
					}).exec();
				}).exec();
			},
			// 显示插入块元素工具栏
			showInsertBlockView() {
				this.editorCtx.blur()
				uni.hideKeyboard()
				this.showToolSettingMask = true
				this.showInsertBlockToolSetting = true
				this.showToolPopup = false
				this.toolPopupRect = {}

			},
			// 关闭插入块元素工具栏
			closeToolSetting() {
				this.showToolSettingMask = false
				this.showInsertBlockToolSetting = false
			},
			// 编辑器辑器状态改变时触发
			onStatusChange(e) {
				this.formats = e.detail
			},
			// 编辑器获取焦点时触发
			onEditorFocus() {
				// 显示工具栏
				this.showFooterToolBar = true
			},
			// 编辑器失去焦点时触发
			onEditorBlur() {
				// 将键盘高度设置为 0
				this.updatePosition(0)
				// 隐藏工具栏
				this.showFooterToolBar = false
			},
			// 手动隐藏键盘
			hideKeyboard() {
				this.editorCtx.blur()
			},
			// 设置编辑器格式
			format(name, value) {
				// name 不存在时，不设置编辑器格式
				if (!name || !this.editorCtx) return

				// 根据传递的 name 和 value 参数，设置编辑器的格式。
				switch (name) {
					case 'hr':
						// 插入分割线
						this.editorCtx.insertDivider()
						break
					case 'undo':
						// 撤销操作
						this.editorCtx.undo()
						break
					case 'redo':
						// 重做操作
						this.editorCtx.redo()
						break
					case 'link':
						// 插入链接，由于小程序端不支持插入链接，所以在小程序端通过 insertText 方法插入 markdown 格式的链接。在 H5 端，通过 format 方法插入链接。
						// #ifdef H5
						this.editorCtx.format('link', value)
						// #endif

						// #ifndef H5
						this.editorCtx.insertText({
							text: `[${value.text}](${value.link})`
						})
						// #endif
						break
					case 'space-both':
						// 设置两端缩进左右间距
						this.editorCtx.format('marginLeft', value)
						this.editorCtx.format('marginRight', value)
						break
					case 'format-clear':
						// 清除格式
						this.editorCtx.removeFormat()
						break
					case 'image':
						// 插入图片
						this.editorCtx.insertImage(value)
						break
					case 'unlockContent':
						// 插入付费解锁内容块
						const isExist = document.querySelector('.ql-unlock-content')

						// 如果已经存在付费解锁内容块，则弹出提示框，否则插入付费解锁内容块。
						if (isExist) {
							uni.showModal({
								content: '付费解锁不允许重新插入',
								showCancel: false
							})
							return
						}
						this.editorCtx.insertUnlockContent(value)
						break
					case 'ai':
						// 打开AI智能助手
						this.showImChat = !this.showImChat
						break
					case 'mediaVideo':
						// 仅H5支持
						// #ifdef H5
						this.editorCtx.insertMediaVideo(value)
						// #endif
						break
					default:
						this.editorCtx.format(name, value)
						break
				}
				// 插入内容后，将编辑器滚动到底部
				setTimeout(() => this.editorCtx.scrollIntoView(), 100)
			},
			// 获取编辑器所选内容的格式
			getFormat(range) {
				this.formats = range ? this.editorCtx.getFormat(range) : {}
				return this.formats
			},
			// 复制图片进入编辑器上传
			uploadHandlerForH5({
				blob,
				ext,
				size
			}, el) {
				// 返回一个 Promise 对象，以便在上传成功后，将图片的 URL 插入到编辑器中。
				return new Promise((resolve, reject) => {
					this.uploadEditorImage({
						filePath: blob,
						fileExt: ext,
						size
					}).then(fileID => {
						resolve(fileID)
					}).catch(error => {
						// 防止万一，只要检测失败就删除图片
						Quill && Quill.find(el).deleteAt(0)
						uni.showModal({
							content: error.message,
							showCancel: false
						})
						reject()
					}).finally(() => {
						uni.hideLoading()
					})
				})
			},
			onInsertImage(selectMediaItems) {
				const image = selectMediaItems[0]

				this.$refs.insertImageDrawer.close()

				// 图片如果没有违规，调用 format 方法，将图片插入到富文本编辑器中，并滚动到插入的位置。
				this.format('image', {
					src: image.src,
					data: {
						source: image.src
					}
				})
				setTimeout(() => this.editorCtx.scrollIntoView(), 0)
			},
			uploadEditorImage({
				filePath,
				fileExt,
				size
			}) {
				uni.showLoading({
					title: '上传中...'
				})

				return new Promise((resolve, reject) => {
					new Promise((res, rej) => {
						uniCloud.uploadFile({
							filePath,
							cloudPath: `cms/media/images/${Date.now()}_${Math.round(Math.random() * 10000)}.${fileExt || 'jpg'}`,
							fileType: 'image',
							success: _res => {
								res(_res)
							},
							fail: error => {
								rej(error)
							},
							complete: () => {
								uni.hideLoading()
							}
						})
					}).then(res => {
						uni.showLoading({
							title: '图片检测中...'
						})

						const uniCmsCo = uniCloud.importObject('uni-cms-co', {
							customUI: true
						})

						return uniCmsCo.checkImageSec(res.fileID).then(() => {
							return res.fileID
						})
					}).then(fileID => {
						const isCloudFile = fileID.startsWith('cloud://')

						if (!isCloudFile) return fileID

						return uniCloud.getTempFileURL({
							fileList: [fileID]
						}).then(res => {
							if (res.fileList && res.fileList.length) {
								return res.fileList[0].tempFileURL
							}

							return fileID
						})
					}).then(fileID => {
						uni.showLoading({
							title: '上传媒体库...'
						})

						const uniMediaLibrary = uniCloud.importObject('uni-media-library-co', {
							customUI: true
						})

						return new Promise((_resolve) => {
							const image = new Image()
							image.onload = () => {
								_resolve({
									fileID,
									width: image.width,
									height: image.height
								})
							}

							image.src = fileID
						}).then(({
							fileID,
							width,
							height
						}) => {
							return uniMediaLibrary.report({
								src: fileID,
								cover: fileID,
								type: 'image',
								originalName: filePath.split('/').pop(),
								fileType: fileExt || 'jpg',
								size,
								resolution: {
									width,
									height
								},
								uploadUser: uniCloud.getCurrentUserInfo().uid
							})
						}).then(() => {
							return fileID
						}).catch(e => {
							console.log(e, 'e')
						})
					}).then((fileID) => {
						resolve(fileID)
					}).catch(error => {
						reject(error)
					}).finally(() => {
						uni.hideLoading()
					})
				})
			},
			// 在移动端插入超链接
			showLinkPopup(link) {
				this.currentLink.url = link
				this.hideKeyboard()
				this.$refs.popup.open()
			},
			// 插入超链接
			linkChange() {
				if (!this.currentLink.url) return
				this.format('link', {
					text: this.currentLink.title || this.currentLink.url,
					link: this.currentLink.url
				})
				this.$refs.popup.close()
			}
		}
	}
</script>

<style scoped lang="scss">
	// #ifdef H5
	@import '@/uni_modules/uni-cms/common/style/editor-icon.css';
	// #endif

	/* #ifdef H5 */
	@import "quill.scss";
	/* #endif */

	@media screen and (max-width: 768px) {
		@import "app.scss";
	}

	@media screen and (min-width: 768px) {
		@import "h5.scss";
	}


	.popup-body {
		background: #fff;
		padding: 30px;
		border-radius: 4px;
		max-width: 80%;
		margin: 0 auto;

		.tip {
			font-size: 14px;
			text-align: center;
			color: #666;
			margin-bottom: 10px;
		}

		.popup-body-btn-group {
			text-align: center;

			.btn {
				margin: 0 5px;
			}
		}
	}

	// 修改编辑器默认样式
	::v-deep .ql-container {
		.ql-editor {
			&.ql-blank:before {
				font-style: normal;
				line-height: 1.75;
				font-size: 17px;
			}

			@mixin font {
				font-size: 17px;
				line-height: 1.75;
			}

			@mixin mb {
				margin-bottom: 20px;
			}

			.ql-syntax {
				@include mb;
			}

			p {
				@include font;
				@include mb;
			}

			h1,
			h2,
			h3,
			h4,
			h5,
			h6 {
				@include mb;
			}

			ol,
			ul {
				@include font;
				@include mb;

				li {
					margin-bottom: 10px !important;

					&:last-child {
						margin-bottom: 0;
					}
				}
			}

			.divider {
				@include mb;
			}

			code {
				word-break: break-word;
				border-radius: 2px;
				overflow-x: auto;
				background-color: #fff5f5;
				color: #ff502c;
				padding: 0.065em 0.4em;
				font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
			}
		}
	}

	.uni-im-chat-components {
		width: 450px;
		position: fixed;
		right: 50px;
		bottom: 70px;
		z-index: 999;
		border: #fefefe solid 2px;
		box-shadow: 0 0 10px rgba(0, 0, 0, .1);
		border-radius: 8px;
		overflow: hidden;

		.close-bar {
			height: 50px;
			background: #fff;
			display: flex;
			align-items: center;
			padding: 0 10px;
			justify-content: flex-end;
			position: relative;

			.head {
				display: flex;
				position: absolute;
				left: 0;
				right: 0;
				text-align: center;
				flex-direction: column;
				gap: 5px;

				.title {
					font-size: 14px;
					font-weight: bold;
					color: #333;
					padding-bottom: 0;
					border: none;
				}

				.desc {
					font-size: 12px;
					color: #999;
				}
			}

			.close {
				width: 30px;
				height: 30px;
				background: #f1f1f1;
				border-radius: 50%;
				display: flex;
				align-items: center;
				justify-content: center;
				position: relative;
				z-index: 2;
				cursor: pointer;

				.icon {
					display: block;
				}
			}
		}

		::v-deep {
			//* {
			//  max-width: 100%;
			//}

			.page {
				height: 720px;
			}

			.container {
				width: 100%;
				height: 100%;
				margin: 0;
				box-shadow: none;
				flex: 1;
				border-radius: 0;
			}

			.menu {
				padding: 0;
			}

			.msg-item {
				.content {
					max-width: 88%;
				}
			}

			.trash {
				width: auto;
			}

			.foot-box {
				gap: 10px;
				padding: 10px;

				.send {
					width: 50px;
				}

				.textarea-box {
					flex: 1;
					width: auto;

					.textarea {
						width: 100%;
					}
				}
			}
		}
	}

	@media screen and (max-width: 768px) {
		.uni-im-chat-components {
			width: 100%;
			left: 0;
			right: 0;
			bottom: 0;
			margin: 0 auto;
			border: none;

			&:before {
				content: "";
				position: fixed;
				top: 0;
				left: 0;
				right: 0;
				bottom: 0;
				background: rgba(0, 0, 0, .5);
				z-index: -1;
			}

			//
			//::v-deep {
			//  .page {
			//    height: 75vh;
			//  }
			//
			//  .foot-box {
			//    width: 100%;
			//  }
			//  .foot-box-content {
			//    width: 100%;
			//    display: flex;
			//    align-items: center;
			//    gap: 10px;
			//  }
			//}
		}
	}
</style>